﻿/**
 * Search Engine Keyword Highlight.
 *
 * This module can be imported by any HTML page, and it would analyse the
 * referrer for search engine keywords, and then highlight those keywords on
 * the page, by wrapping them around <span class="hilite">...</span> tags.
 * Document can then define styles else where to provide visual feedbacks.
 *
 * Usage:
 *
 *   In HTML. Add the following line towards the end of the document.
 *
 *     <script type="text/javascript" src="se_hilite.js"></script>
 *
 *   In CSS, define the following style:
 *
 *     .hilite { background-color: #ff0; }
 *
 *   If Keyword.style_name_suffix is true, then define the follow styles:
 *
 *     .hilite1 { background-color: #ff0; }
 *     .hilite2 { background-color: #f0f; }
 *     .hilite3 { background-color: #0ff; }
 *     .hilite4 ...
 *
 * @author Scott Yang <http://scott.yang.id.au/>
 * @version 1.1
 */

 /**
  * This script was modified by Alex zhang.
  *
  * Added following features:
  *   1. get support for keywords which were encoded in GB2312 codeset.
  *   2. index the keywords in the top of the page, can easily link to
  *      the keyword where it first shows by clicking on the index.
  *   3. get support for most chinese Search Engines.
  *   4. sucking the keywords from the META tag for generating the link
  *      which makes a related search by a Search Engine.
  *   5. a little other changes in the onload event for some special
  *      purposes in this site.
  *
  * Notes:
  *   the changed script need to call an extenal vbscript function for
  *   decoding the keywords which were encoded in gb2312 codeset, like
  *   Baidu does. so under Firefox 1.0 pro version, it doesn't work, as
  *   a solution, this script will ignore the chinese one and deal next.
  *   the vbscript function named chrval() is defined in chr.vbs
  *
  * @revised author Alex Zhang<http://www.aiview.com/>
  * @revised version 1.3.0
  * @revised created on Nov 29, 2004
  * @revised modified on Feb 7, 2007
  *
  * If any question or suggestion, pls. drop me a line by www.aiview.com.
  * Fot using this revised version, you can visit a guide page at:
  * http://www.aiview.com/2005/08/highlight_keywords_with_javascript.html
  */

// Configuration:
Keyword = {
    /**
     * Whether to automatically hilite the keywords when the HTML document
     * has been fully loaded.
     * If this parameter is set to false, the parameter called "index" below
     * will be disabled.
     */
    hilite: true,

    /**
     * Whether to automatically index the HTML document by the keywords.
     * It depends the parameter above called "hilite" to be set as true.
     */
    index: true,

    /**
     * Whether to automatically refill in the textbox with the Keywords which
     * was got from the referer link. the textbox is named with the parameter
     * defined below "element1".
     */
    refill1: true,

    /**
     * Whether to automatically refill in the textbox with the Keywords which
     * was sucked from the Mata tag. the textbox is named with the parameter
     * defined below "element2".
     */
    refill2: false,

    /**
     * Name of the input tag in HTML file. This one is defined in the
     * elder site.
     */
    element1: 'search',

    /**
     * Name of the input tag in HTML file. This one is for the Related
     * Search feature.
     */
    element2: 'w',

    /**
     * Name of the style to be used. Default to 'hilite'.
     */
    style_name: 'hilite',

    /**
     * Whether to use different style names for different search keywords by
     * appending a number starting from 1, i.e. hilite1, hilite2, etc.
     */
    style_name_suffix: true,

    /**
     * Set it to override the document.referrer string. Used for debugging
     * only.
     */
    // An URL included hostname and query string.
    //debug_referrer: 'http://www.google.cn/search?q=a++%E4%B8%AD%E5%9B%BD&complete=1&hl=zh-CN&newwindow=1&btnG=Google+%E6%90%9C%E7%B4%A2&meta=&aq=f&oq=',
    //debug_referrer: 'http://www.baidu.com/s?wd=%D6%D0%B9%FA',
     debug_referrer:'',
    // A string of keywords splited by ','.
    debug_meta: ''
};

/**
 * Decode the referrer string and return a list of search keywords.
 */
Keyword.decodeReferrer = function(referrer) {
    /* Can't decide if there's an utf-8 encoding or a gb2312 encoding by TRY.
       although it works in some cases, but does not in others.
       To decide this by Search Engine name instead of following code.
       If there's any better way you known, tell me, I'll thank you very much!
    try {
        // to decode the url of utf-8.
        referrer = decodeURIComponent(referrer);
    } catch (e) {
        // to decode the url of gb2312.
        referrer = Keyword.decodeGBURI(referrer);
    }*/
    var query = null;

    if (referrer.match(/^http:\/\/(www\.)?alltheweb.*/i)) {
    // AllTheWeb
        referrer = decodeURIComponent(referrer);
        if (referrer.match(/[&\?]+q=/))
            //query = referrer.replace(/^.*q=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+q=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/(?:seek|cns)\.3721.*/i)) {
    // 3721 GB
        referrer = Keyword.decodeGBURI(referrer);
        if (referrer.match(/[&\?]+p=/))
            //query = referrer.replace(/^.*p=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+p=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/(?:www|image|cache)?\.baidu.*/i)) {
    // Baidu GB
        referrer = Keyword.decodeGBURI(referrer);
        if (referrer.match(/[&\?]+(w|wd|word)=/))
            //query = referrer.replace(/^.*(w|wd|word)=([^&]+)&?.*$/i, '$2');
            if (referrer.match(/^.*[&\?]+(w|wd|word)=([^&]+)&?.*$/i))
                query = RegExp.$2;
    } else if (referrer.match(/^http:\/\/(www|image)?\.?google.*/i)) {
    // Google
        referrer = decodeURIComponent(referrer);
        if (referrer.match(/[&\?]+q=/))
            //query = referrer.replace(/^.*q=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+q=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/search\.lycos.*/i)) {
    // Lycos
        referrer = decodeURIComponent(referrer);
        if (referrer.match(/[&\?]+query=/))
            //query = referrer.replace(/^.*query=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+query=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/search\.msn.*/i)) {
    // MSN
        referrer = decodeURIComponent(referrer);
        if (referrer.match(/[&\?]+q=/))
            //query = referrer.replace(/^.*q=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+q=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/search\.tom.*/i)) {
    // TOM GB
        referrer = Keyword.decodeGBURI(referrer);
        if (referrer.match(/[&\?]+word=/))
            //query = referrer.replace(/^.*word=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+word=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/(search|so)\.qq.*/i)) {
    // QQ GB
        referrer = Keyword.decodeGBURI(referrer);
        if (referrer.match(/[&\?]+word=/))
            //query = referrer.replace(/^.*word=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+word=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/search\.yahoo.*/i)) {
    // Yahoo
        referrer = decodeURIComponent(referrer);
        if (referrer.match(/[&\?]+p=/))
            //query = referrer.replace(/^.*p=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+p=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/page\.zhongsou.*/i)) {
    // Zhongsou GB
        referrer = Keyword.decodeGBURI(referrer);
         if (referrer.match(/[&\?]+word=/))
            //query = referrer.replace(/^.*word=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+word=([^&]+)&?.*$/i))
                query = RegExp.$1;
    } else if (referrer.match(/^http:\/\/www\.yisou.*/i)) {
    // Yisou GB
        referrer = Keyword.decodeGBURI(referrer);
        if (referrer.match(/[&\?]+p=/))
            //query = referrer.replace(/^.*p=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+p=([^&]+)&?.*$/i))
                query = RegExp.$1;
    /**
     * If you are using Movable Type and enabled the MT search,
     * for the support of Hiliting the keywords by MT search, you
     * need to:
     *   1. Change the domain name to yours.
     *   2. Change the decode method by your page charset.
     *        It's could be found at mt.cfg or mt-config.cgi
     *        utf-8 use decodeURIComponent()
     *        gb2312 use Keyword.decodeGBURI()
     */
    } else if (referrer.match(/^http:\/\/www\.aiview.*/i)) {
    // Aiview.com
        referrer = decodeURIComponent(referrer);
        if (referrer.match(/search=/))
            //query = referrer.replace(/^.*search=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*search=([^&]+)&?.*$/i))
                query = RegExp.$1;
    }
    else{
    // www.gsdzsw.com tjb
        referrer = decodeURIComponent(window.location);
        if (referrer.match(/[&\?]+seacha=/))
            //query = referrer.replace(/^.*search=([^&]+)&?.*$/i, '$1');
            if (referrer.match(/^.*[&\?]+seacha=([^&]+)&?.*$/i))
                query = RegExp.$1;
    }

    if (query) {
        query = query.replace(/\'|"/, '');
        query = query.split(/[\s,\+\.]+/);
    }

    return query;
};

/**
 * Highlight a HTML string with a list of keywords.
 */
Keyword.hiliteHTML = function(html, query) {
    var re = new Array();
    for (var i = 0; i < query.length; i ++) {
        if (query[i]) {
            var classname = Keyword.style_name;
            if (Keyword.style_name_suffix)
                classname += (re.length==0?'':re.length);
            if("&nbsp;".indexOf(query[i])<0)
                re.push([new RegExp('('+query[i]+')', "gi"), classname]);
        }
    }

    var last = 0;
    var tag = '<';
    var skip = false;
    var skipre = new RegExp('^(script|style|textarea)', 'gi');
    var part = null;
    var result = '';

    while (last >= 0) {
        var pos = html.indexOf(tag, last);
        if (pos < 0) {
            part = html.substring(last);
            last = -1;
        } else {
            part = html.substring(last, pos);
            last = pos+1;
        }

        if (tag == '<') {
            if (!skip) {
                for (var j = 0; j < re.length; j ++)
                    part = part.replace(re[j][0], '<span class="' + re[j][1] + '">$1</span>');
            } else
                skip = false;
        } else if (part.match(skipre)) {
            skip = true;
        }

        result += part + (pos < 0 ? '' : tag);
        tag = tag == '<' ? '>' : '<';
    }
    return result;
};

/**
 * Index a HTML string with a list of keywords and generate anchors
 * (internal links) for the index.
 */
Keyword.indexHTML = function(html, query) {
    var re = new Array();
    var q = 'Your keywords (link to the first macthing)';
       for (var i = 0; i < query.length; i ++) {
        if (query[i]) {
            var classname = Keyword.style_name;
            if (Keyword.style_name_suffix)
                classname += (re.length==0?'':re.length);
            re.push([new RegExp('('+query[i]+')', "gi"), classname]);
            q += '<span class="' + classname + '">' + (query[i]).link('#kIdx' + i) + ' </span>';
        }
    }

    var last = 0;
    var tag = '<';
    var skip = false;
    var skipre = new RegExp('^(script|style|textarea)', 'gi');
    var part = null;
    var result = '';

    while (last >= 0) {
        var pos = html.indexOf(tag, last);
        if (pos < 0) {
            part = html.substring(last);
            last = -1;
        } else {
            part = html.substring(last, pos);
            last = pos+1;
        }

        if (tag == '<') {
            if (!skip) {
                for (var j = 0; j < re.length; j ++) {
                    part = part.replace(re[j][0], ''.anchor('kIdx' + j) + '$1');
                }
            } else
                skip = false;
        } else if (part.match(skipre)) {
            skip = true;
        }

        result += part + (pos < 0 ? '' : tag);
        tag = tag == '<' ? '>' : '<';
    }
    result = q + '<p>' + result;
    return result;
};

/**
 * Highlight a DOM element with a list of keywords.
 */
Keyword.hiliteElement = function(elm, query) {
    if (!query)
        return;

    elm.innerHTML = Keyword.hiliteHTML(elm.innerHTML, query);
};

/**
 * Index a DOM element with a list of keywords.
 */
Keyword.indexElement = function(elm, query) {
    if (!query)
        return;

    elm.innerHTML = Keyword.indexHTML(elm.innerHTML, query);
};

/**
 * Set the value for a DOM element with a list of keywords.
 */
Keyword.refillElement = function(elm, query) {
    if (document.getElementById(elm) && query)
        document.getElementById(elm).value = query;
}

/**
 * Highlight a HTML document using keywords extracted from document.referrer.
 * This is the main function to be called to perform search engine highlight
 * on a document.
 *
 * Currently it would check for DOM element 'content', element 'container' and
 * then document.body in that order, so it only highlights appropriate section
 * on WordPress and Movable Type pages.
 */
Keyword.run = function() {
    // If 'debug_referrer' then we will use that as our referrer string
    // instead.
    var q1 = Keyword.debug_referrer ? Keyword.debug_referrer : document.referrer;
    if (document.getElementById('keywords'))
        var q2 = Keyword.debug_meta ? Keyword.debug_meta : document.getElementById('keywords').content;
    q1 = Keyword.decodeReferrer(q1);
    if (q2)
        q2 = q2.split(',', 2);

    if (q1) {
        if (Keyword.hilite) {
            var e = null;
            if ((e = document.getElementById('container')))
            {
                Keyword.hiliteElement(e, q1);
                if (Keyword.index) {
                    Keyword.indexElement(e, q1);
                }
            }
            else{
                window.status="Hilight container is not body";
            
            }
        }

        if (Keyword.refill1) {
            var query = q1.join(' ');
            Keyword.refillElement(Keyword.element1, query);
        }
    }

    if (q2) {
        if (Keyword.refill2) {
            var query = q2[0] + (q2[1] ? (' ' + q2[1]) : '');
            if (query)
                Keyword.refillElement(Keyword.element2, query);
        }
    }
    Keyword.other();
};

/**
 * Decode an URI which contains encoded GB2312 string.
 * For example, Baidu.com will generate a encoded GB2312 URI,
 * should call this function before write it to Browser.
 * Google.com will generate a encoded UTF-8 URI, so don't
 * need this function.
 */
Keyword.decodeGBURI = function(strcode) {
    try {
        var result = '';
        for ( var i = 0; i < strcode.length; i ++) {
            var thischr = strcode.substr(i,1);

            if (thischr == '%') { //  HEX encoded
                var ascii = eval('0x' + strcode.substr(i+1,2)); // Convert 2 bytes in HEX to Ascii in DEC

                if ((ascii > 0x20 && ascii < 0x30) ||
                    (ascii > 0x39 && ascii < 0x41) ||
                    (ascii > 0x5a && ascii < 0x61) ||
                    (ascii > 0x7a && ascii < 0x91)) { // !"#$%&'()*+,-./ :;<=>?@ [\]^_;` {|}~
                    try {
                        result = result + String.fromCharCodeAt(ascii); //  Double-bytes to single-byte
                    } catch (e)    { // ie6 will trap here and skip above process
                        i = i + 2;
                        continue;
                    }

                    i = i + 2;
                } else { // Wide-Character
                    ascii = eval('0x' + strcode.substr(i+1,2) + strcode.substr(i+4,2)); // Convert 4 bytes in HEX to Ascii in DEC
                    try    {
                        result = result + chrval(ascii); // Revers to double char, call vb func to process gb2312 encoded char
                    } catch (e) { // non-ie browser don't support vb script, then skip this wide-char, go next
                        i = i + 5;
                        continue;
                    }
                    i = i + 5;
                }
            } else if (thischr == '+')
                    result = result + ' '; // Convert '+' to space

            else // Ascii char, no need process
                    result = result + thischr;
        }
    } catch(e) { return false; };

    return result;
};

/**
 * Additional function, you can put any code here for any other purpose
 * out from Hilite.
 * Any code put here will be run after the HTML document has been fully
 * loaded.
 * If you are downloading this Hilite program from my website, the code
 * here might not adapt to you, you can delete all code in the function.
 * If you don't understand what this function really means, just keep it
 * nothing.
 */
Keyword.other = function() {
    try {
        if (document.baidu.word)
            document.baidu.word.select();
    }
    catch (e) {}
};

/* Trigger the highlight using the onload handler.
 */

// Only for Mozila/Firefox Browser
if (document.addEventListener) {
    document.addEventListener("DOMContentLoaded", Keyword.run, false);
}

// Only for IE
   /*@cc_on @*/
   /*@if (@_win32)
       document.write("<script defer src=/ie_onload.js><"+"/script>");
   /*@end @*/

// For all other Browsers
if (window.onload) {
    Keyword._old_onload = window.onload;
    window.onload = function(ev) {
        Keyword._old_onload(ev);
        Keyword.run();
    };
} else {
    window.onload = function() {
        Keyword.run();
    };
}